/*
 * Created by SharpDevelop.
 * User: Michael
 * Date: 13/09/2007
 * Time: 10:15 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */

using System;
using System.Collections.Generic;

namespace SudokuSolver
{
	/// <summary>
	/// Description of SudokuGame.
	/// </summary>
	public class SudokuGame
	{
		private List<Group> _Rows = new List<Group>();
		private List<Group> _Columns = new List<Group>();
		private List<Group> _Blocks = new List<Group>();
		private List<Technique> _Techniques = new List<Technique>();
		
		public event EventHandler Updated;
		
		public List<Group> Blocks 
		{
			get { return _Blocks; }
		}
		
		public List<Group> Columns 
		{
			get { return _Columns; }
		}
		public List<Group> Rows 
		{
			get { return _Rows; }
		}
		
		public bool Solved
		{
			get
			{
				bool temp = true;
				foreach(Group row in _Rows)
				{
					if(!(row.Solved))
						temp = false;
				}
				return temp;
			}
		}
		
		private int CalculateBlockNumber(int column, int row)
		{
			int blocknum = 1;
			if (column > 3)
				blocknum++;
			if (column > 6)
				blocknum++;
			if (row > 3)
				blocknum += 3;
			if (row > 6)
				blocknum += 3;
			
			return blocknum;
		}
		
		public SudokuGame()
		{
			//give me 9 rows, columns and blocks
			for(int i = 0; i < 9; i++)
			{
				_Rows.Add(new Group());
				_Columns.Add(new Group());
				_Blocks.Add(new Group());
			}
			//now give me 81 cells and put each one in a row, column and block
			//9 columns
			for(int column = 0; column < 9; column++)
			{
				//9 rows
				for(int row = 0; row < 9; row++)
				{
					int block = CalculateBlockNumber(column+1, row+1);
					Cell tempCell = new Cell(_Rows[row], row, _Columns[column], column, _Blocks[block - 1], block);
					_Rows[row].AddCell(tempCell);
					_Columns[column].AddCell(tempCell);
					//put it in the appropriate block too
					_Blocks[block - 1].AddCell(tempCell);
				}
			}
			
			//TODO: Add the techniques here once they're created...
			_Techniques.Add(new SliceAndDice());
			_Techniques.Add(new LoneNumbers());
			_Techniques.Add(new SingleOption());
			_Techniques.Add(new Pairs());
			_Techniques.Add(new BlockLine());
			_Techniques.Add(new HiddenSubsets());
			//_Techniques.Add(new Colouring());
		}
		
		public List<string> DrawGame()
		{
			List<string> returnList = new List<string>();
			//draw them rows at a time...
			for(int i = 0; i <= 2; i++)
			{
				//draw one row
				returnList.Add(_Rows[i].ToString());
			}
			returnList.Add("-----------");
			for(int i = 3; i <= 5; i++)
			{
				//draw one row
				returnList.Add(_Rows[i].ToString());
			}
			returnList.Add("-----------");
			for(int i = 6; i <=8; i++)
			{
				//draw one row
				returnList.Add(_Rows[i].ToString());
			}
			return returnList;
		}
		
		public bool Solve()
		{
			bool change;
			do
			{
				change = false;
				foreach(Technique tech in _Techniques)
				{
					if(tech.Run(this))
					{
						if(Updated != null) Updated(this, EventArgs.Empty);
						change = true;
					}
				}
			} while(change == true);
			return Solved;
		}
		
		public int CountFound()
		{
			int count = 0;
			foreach(Group row in _Rows)
			{
				foreach(Cell cell in row.Cells)
				{
					if(cell.Found)
						count++;
				}
			}
			
			return count;
		}
	}
}
